home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / risc_src.lha / risc_sources / sys / eval.t < prev    next >
Text File  |  1990-01-30  |  34KB  |  902 lines

  1. (herald (tsys eval)    ;** dont change this herald
  2.         (env tsys (osys kernel)))
  3.  
  4. ;;; Copyright (c) 1985 Yale University
  5. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  6. ;;; This material was developed by the T Project at the Yale University Computer 
  7. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  8. ;;; and to use it for any purpose is granted, subject to the following restric-
  9. ;;; tions and understandings.
  10. ;;; 1. Any copy made of this software must include this copyright notice in full.
  11. ;;; 2. Users of this software agree to make their best efforts (a) to return
  12. ;;;    to the T Project at Yale any improvements or extensions that they make,
  13. ;;;    so that these may be included in future releases; and (b) to inform
  14. ;;;    the T Project of noteworthy uses of this software.
  15. ;;; 3. All materials developed as a consequence of the use of this software
  16. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  17. ;;;    of acknowledging credit in academic research.
  18. ;;; 4. Yale has made no warrantee or representation that the operation of
  19. ;;;    this software will be error-free, and Yale is under no obligation to
  20. ;;;    provide any services, by way of maintenance, update, or otherwise.
  21. ;;; 5. In conjunction with products arising from the use of this material,
  22. ;;;    there shall be no use of the name of the Yale University nor of any
  23. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  24. ;;;    without prior written consent from Yale in each case.
  25. ;;;
  26.  
  27. ;;;; The Evaluator
  28.  
  29. ;;; COMPILE is an S-expression preprocessor.  It takes source code,
  30. ;;; represented as S-expression, and makes a code tree.  Its main
  31. ;;; purposes are (a) expanding macros and (b) dead-reckoning local
  32. ;;; variable references.  This preprocessing makes code run faster
  33. ;;; than it would if a straightforward S-expression interpreter was
  34. ;;; used.
  35.  
  36. ;;; For the purposes of this module, the terms "static" and "global"
  37. ;;; both mean "free with respect to the expression being compiled".
  38. ;;; "Local" or "lambda-bound" mean "bound by some lambda-expression
  39. ;;; within the expression being compiled".
  40.  
  41. ;;; Code ("S-code") trees are represented as closures.  To interpret
  42. ;;; a code tree it is only necessary to call it.
  43.  
  44. ;;; A SHAPE is a compile-time structure which describes the
  45. ;;; representation that the local variable environment will have
  46. ;;; at runtime.
  47.  
  48. ;;; EVAL: copied from the T manual.
  49.  
  50. (define (eval exp env)
  51.   (run-compiled-code (standard-compiler exp (env-syntax-table env))
  52.                      env))
  53.  
  54. (define (standard-compiler exp syntax)
  55.   (compile-top exp syntax nil))
  56.  
  57. (lset *current-module* nil)
  58.  
  59. ;;; Like STANDARD-COMPILER, but gets its input from a port.  Sets
  60. ;;; up a compiled expression which is a loaded-file; i.e. handles
  61. ;;; LOADED-FILE-HERALD and LOADED-FILE-SOURCE appropriately.
  62.  
  63. (define-constant initial-exp-values (list (undefined-value "empty file")))
  64.  
  65.  
  66. (define (standard-compile-port port syntax herald)
  67.   (let ((source (port-name port)))
  68.     (bind ((*current-module* source))
  69.       (object nil
  70.               ((run-compiled-code self env)
  71.                (iterate loop ((vals initial-exp-values))
  72.                  (let ((exp (read port)))
  73.                    (cond ((eof? exp)
  74.                           (set port nil)            ;drop pointer
  75.                           (apply return vals))
  76.                          (else
  77.                           (receive vals
  78.                                    (run-compiled-code
  79.                                     (compile-top exp syntax self)
  80.                                     env)
  81.                             (load-print vals)
  82.                             (loop vals)))))))
  83.               ((compiled-code? self) '#t)
  84.               ((get-loaded-file self) self)
  85.               ((loaded-file-herald self) herald)
  86.               ((loaded-file-source self) source)
  87.               ((identification self)        ; For BACKTRACE
  88.                (filename-name (herald-filename herald)))
  89.               ((print-info self)
  90.                (filename-name (herald-filename herald)))
  91.               ((print-type-string self) "Loaded-file")))))
  92.  
  93. ;;; COMPILE-TOP - this is the top-level entry into the compiler.
  94. ;;; Keeps track of all variables free in the expression; when the
  95. ;;; code is actually run, it creates a vector where locatives to
  96. ;;; the variables can be stored.
  97.  
  98. (lset *syntax-table*   nil)
  99. (lset *free-vars*      nil)
  100. (lset *free-var-count* 0)
  101.  
  102. (define (compile-top exp syntax loaded-file)
  103.   (bind ((*free-vars* (make-table '*free-vars*))
  104.          (*free-var-count* 1)
  105.          (*syntax-table* syntax))
  106.     (let* ((code (compile exp loaded-file nil))
  107.            (free-var-count *free-var-count*))
  108.       (object nil
  109.               ((run-compiled-code self env)
  110.                (let ((env (enforce environment? env))
  111.                      (genv (vector-fill (make-vector free-var-count) nil)))
  112.                  (set (vref genv 0) env)
  113.                  ;? (add-active-segment env genv)
  114.                  (run code env genv)))
  115.               ((print-type-string self) "Compiled-code")))))
  116.  
  117. (define-integrable (genv-env genv) (vref genv 0))
  118.  
  119. ;;; ---- Local variable spec stuff.
  120.  
  121. ;;; Local variable specifiers (LVSPEC's) are implemented as fixnums
  122. ;;; divided into two bit fields, BACK and OVER.
  123.  
  124. (define-integrable lvspec? fixnum?)
  125.  
  126. (define-integrable (add-contour args lenv) (cons lenv args))
  127.  
  128. (define-integrable (lvspec back over)
  129.   (fixnum-logior back (fixnum-ashl over 13)))
  130.  
  131. (define-integrable (lvspec-back spec)
  132.   (fixnum-logand spec 8191))
  133.  
  134. (define-integrable (lvspec-over spec)
  135.   (fixnum-ashr spec 13))               ; signed
  136.  
  137. (define-integrable cenv-first cdr)
  138. (define-integrable cenv-rest  car)
  139. (define-integrable cenv-end?  atom?)
  140.  
  141. (define-integrable lenv-first cdr)
  142. (define-integrable lenv-rest  car)
  143. (define-integrable lenv-end?  atom?)
  144.  
  145. ;;; ---- Utilities for the stack debugger.
  146.  
  147. (define (interpreter-frame? frame)
  148.   ;; Incredible kludge.
  149.   (let ((z (get-loaded-file frame)))
  150.     (and z
  151.          (let ((fn (herald-filename (loaded-file-herald z))))
  152.            (and (eq? (filename-name fn) 'eval)
  153.                 (eq? (filename-dir fn) 'tsys)
  154.                 (frame-any (lambda (x)
  155.                          (or (scode? x)
  156.                  (and (pair? x) (scode? (car x)))))
  157.                 frame))))))
  158.  
  159. (define (interpreter-frame-code frame)
  160.   (frame-any (lambda (obj)
  161.                (cond ((scode? obj) obj)
  162.              ((and (pair? obj) (scode? (car obj)))
  163.               (car obj))
  164.              (else nil)))
  165.              frame))
  166.  
  167.  
  168. ;;; Called from GET-ENVIRONMENT.
  169.  
  170. (define (interpreter-frame-env frame)
  171.   (let ((code (interpreter-frame-code frame)))
  172.     (and code
  173.          (let ((shape (get-shape code)))
  174.            (and shape
  175.                 (let ((lenv (frame-any heuristically-lenv? frame)))
  176.                   (cond (lenv (make-local-env shape lenv))
  177.                         (else (get-environment shape)))))))))
  178.  
  179.  
  180. ;;; (RUN code lenv genv) -> value
  181. ;;;     is the way to run a piece of intermediate code.
  182.  
  183. (define-integrable (run code lenv genv)
  184.   (*run* lenv genv code))      ; make TN's pack better?? ;++ flush
  185.  
  186. (define (standard-run lenv genv code)
  187.   (cond ((lvspec? code)                 ; Local variable
  188.          (fetch-from-lenv code lenv))
  189.         ((extend? code)                 ; General expression
  190.          (code lenv genv))
  191.         (else                           ; Literal
  192.          code)))
  193.  
  194. (lset *run* standard-run)
  195.  
  196. ;;; (SCODE (LAMBDA (lenv genv) . body) . methods) is the standard
  197. ;;; way to create code tree nodes.  S-code is the term from MIT
  198. ;;; Scheme for intermediate code.
  199.  
  200. (lset *scode-count* 0)
  201.  
  202. ;++ changed for T3 objects
  203.  
  204. (define-local-syntax (scode . rest)
  205.   `(block (set *scode-count* (fx+ *scode-count* 1))
  206.           (object ,@rest 
  207.             ((scode? self) t)
  208.             ((disclose self)
  209.              (cond ((get-shape self)
  210.                     => (lambda (shape) (disclose-scode self shape)))
  211.                    (else nil)))
  212.             ((get-proc-name self)
  213.              (cond ((get-shape self)
  214.                     => get-proc-name)
  215.                    (else nil)))            ; ???
  216.             ((get-loaded-file self)
  217.              (cond ((get-shape self)
  218.                     => get-loaded-file)
  219.                    (else nil)))
  220.             ((print-type-string self) "Compiled-expression"))))
  221.  
  222. (define-predicate scode?)
  223.  
  224. (define-operation (get-shape code) nil)
  225.  
  226. (define (empty-shape) nil)
  227.  
  228. (define-operation (disclose-scode code shape)
  229.   (cond ((lvspec? code)
  230.          (invert-lvspec shape code))
  231.         ((extend? code)
  232.          '<expression>)
  233.         (else
  234.          `',code)))
  235.  
  236. (define (disclose-scode-list shape . stuff)
  237.   (map (lambda (code) (disclose-scode code shape)) stuff))
  238.  
  239. ;;; -------------------- Main dispatch.
  240.  
  241. (define (compile exp shape fn?)
  242.   (cond ((atom? exp)
  243.          (compile ((atom-expander *syntax-table*) exp) shape fn?))
  244.         ((not (proper-list? exp))
  245.          (compile-error shape "expression is an improper list~%  ~S" exp))
  246.         (else
  247.          (let ((head (car exp)))
  248.            (cond ((symbol? head)
  249.                   (cond ((syntax-table-entry *syntax-table* head)
  250.                          => (lambda (descr)
  251.                               (cond ((lambda-bound? shape head)
  252.                                      (warning
  253.  '("form beginning with symbol ~S is being interpreted as a~%"
  254.    "**~13tspecial form and not as a call~%"     ;Weird indentation^2
  255.    "**~13t~S~%")
  256.                                              head
  257.                                              exp)))
  258.                               (compile-special-form descr exp shape fn?)))
  259.                         (else
  260.                          (compile-call exp shape))))
  261.                  ((syntax-descriptor? head)
  262.                   (compile-special-form head exp shape fn?))
  263.                  (else
  264.                   (compile-call exp shape)))))))
  265.  
  266. (define (compile-special-form descr exp shape fn?)
  267.   (let ((new-exp (check-special-form-syntax descr exp)))
  268.     (cond ((neq? exp new-exp)
  269.            ;; An error was reported, and luser gave us a new form.
  270.            (compile new-exp shape fn?))
  271.           ((table-entry compilator-table descr)
  272.            ;; Syntax primitively understood by this evaluator.
  273.            => (lambda (proc) (proc descr exp shape fn?)))
  274.           (else
  275.            ;; Non-primitive syntax; assume it's a macro.
  276.            (compile (expand-macro-form descr exp *syntax-table*)
  277.                     shape
  278.                     fn?)))))
  279.  
  280. (define (compile-call exp shape)
  281.   (let ((proc (compile (car exp) shape t))
  282.         (args (map (lambda (arg) (compile arg shape nil))
  283.                    (cdr exp))))
  284.     (case (length (cdr exp))
  285.       ((0) (scode (lambda (lenv genv) ((run proc lenv genv)))
  286.                   ((get-shape self) shape)
  287.                   ((disclose-scode self shape)
  288.                    (disclose-scode-list shape proc))))
  289.       ((1) (let ((arg0 (car args)))
  290.              (scode (lambda (lenv genv)
  291.                       ((run proc lenv genv) (run arg0 lenv genv)))
  292.                     ((get-shape self) shape)
  293.                     ((disclose-scode self shape)
  294.                      (disclose-scode-list shape proc arg0)))))
  295.       ((2) (let ((arg0 (car args))
  296.                  (arg1 (cadr args)))
  297.              (scode (lambda (lenv genv)
  298.                       ((run proc lenv genv) (run arg0 lenv genv)
  299.                                             (run arg1 lenv genv)))
  300.                     ((get-shape self) shape)
  301.                     ((disclose-scode self shape)
  302.                      (disclose-scode-list shape proc arg0 arg1)))))
  303.       ((3) (let ((arg0 (car args))
  304.                  (arg1 (cadr args))
  305.                  (arg2 (caddr args)))
  306.              (scode (lambda (lenv genv)
  307.                       ((run proc lenv genv) (run arg0 lenv genv)
  308.                                             (run arg1 lenv genv)
  309.                                             (run arg2 lenv genv)))
  310.                     ((get-shape self) shape)
  311.                     ((disclose-scode self shape)
  312.                      (disclose-scode-list shape proc
  313.                                           arg0 arg1 arg2)))))
  314.       ((4) (let ((arg0 (car args))
  315.                  (arg1 (cadr args))
  316.                  (arg2 (caddr args))
  317.                  (arg3 (car (cdddr args))))
  318.              (scode (lambda (lenv genv)
  319.                       ((run proc lenv genv) (run arg0 lenv genv)
  320.                                             (run arg1 lenv genv)
  321.                                             (run arg2 lenv genv)
  322.                                             (run arg3 lenv genv)))
  323.                     ((get-shape self) shape)
  324.                     ((disclose-scode self shape)
  325.                      (disclose-scode-list shape proc
  326.                                           arg0 arg1 arg2 arg3)))))
  327.       (else (scode (lambda (lenv genv)
  328.                      (apply (run proc lenv genv)
  329.                             (map (lambda (arg) (run arg lenv genv))
  330.                                  args)))
  331.                    ((get-shape self) shape)
  332.                    ((disclose-scode self shape)
  333.                     (apply disclose-scode-list shape proc args)))))))
  334.  
  335. ;;; The special forms.
  336.  
  337. (define-local-syntax (define-compilator pat args . body)
  338.   (destructure (((name . foo) pat))
  339.     (let ((spect ((*value t-implementation-env 'arglist->argspectrum)
  340.                   foo)))
  341.       `(set (table-entry compilator-table
  342.                          (obtain-syntax-table-entry 
  343.                                (env-syntax-table (the-environment))
  344.                                ',name
  345.                                ',spect))
  346.             (lambda (#f %%exp%% . ,args)
  347.               (destructure ((,foo (cdr %%exp%%)))
  348.                 . ,body))))))
  349.  
  350. (define compilator-table (make-table 'compilator-table))
  351.  
  352. (define-compilator (quote thing) (shape fn?)
  353.   (ignore shape fn?)
  354.   (compile-literal thing))
  355.  
  356. (define (compile-literal obj)
  357.   (cond ((or (fixnum? obj)
  358.              (extend? obj))
  359.          (scode (lambda (lenv genv) (ignore lenv genv) obj)
  360.                 ((disclose-scode self shape)
  361.                  (ignore shape)
  362.                  `',obj)))
  363.         (else                              ; Hack - see RUN
  364.          obj)))
  365.  
  366. (define-compilator (call proc . rest) (shape fn?)
  367.   (compile-call (cons proc rest) fn?))
  368.   
  369. (define compiled-undefined-if-value
  370.   (compile-literal undefined-if-value))
  371.  
  372. (define-compilator (if test con . alts) (shape fn?)
  373.   (let ((test (compile test shape nil))
  374.         (con  (compile con shape fn?))  ; ??
  375.         (alt  (cond ((null? alts) compiled-undefined-if-value)
  376.                     ((null? (cdr alts))
  377.                      (compile (car alts) shape fn?))    ; ??
  378.                     (else
  379.                      (compile-error shape
  380.                                     "illegal IF syntax~%  ~S"
  381.                                     `(if ,test ,con ,@alts))))))
  382.     (scode (lambda (lenv genv)
  383.              (if (run test lenv genv) (run con lenv genv) (run alt lenv genv)))
  384.            ((disclose-scode self shape)
  385.             (cond ((eq? alt compiled-undefined-if-value)
  386.                    `(if ,@(disclose-scode-list shape test con)))
  387.                   (else
  388.                    `(if ,@(disclose-scode-list shape test con alt)))))
  389.            ((get-shape self) shape))))
  390.  
  391. (define-compilator (block . body) (shape fn?)
  392.   (compile-block body shape fn?))
  393.  
  394. (define (compile-block exp-list shape fn?)
  395.   (cond ((null-list? exp-list) (compile-literal nil))
  396.         ((null-list? (cdr exp-list)) (compile (car exp-list) shape fn?))
  397.         (else
  398.          (let ((code (map (lambda (exp) (compile exp shape nil))
  399.                           exp-list)))
  400.            (scode (lambda (lenv genv)
  401.                     (do ((c code (cdr c)))
  402.                         ((null? (cdr c)) (run (car c) lenv genv))
  403.                       (run (car c) lenv genv)))
  404.                   ((get-shape self) shape)
  405.                   ((disclose-scode self shape)
  406.                    `(block ,@(map (lambda (c)
  407.                                     (disclose-scode c shape))
  408.                                   code))))))))
  409.  
  410. ;;; LAMBDA.
  411.  
  412. (define-compilator (lambda vars . body) (shape fn?)
  413.   (compile-lambda nil vars body shape fn?))
  414.  
  415. (define-compilator (named-lambda name vars . body) (shape fn?)
  416.   (compile-lambda name vars body shape fn?))
  417.                           
  418. ;++ (define (duplicate-identifiers? arg-list)
  419. ;++   (iterate loop ((l arg-list))
  420. ;++     (cond ((memq? (car l) (cdr l))
  421. ;++            (error "LAMBDA with duplicate identifier in argument list - ~s~%"
  422. ;++                   (cons name arg-list)))
  423. ;++           (else (loop (cdr l))))))
  424.  
  425. ;++ changed for T3 objects and no more TC bug; removed statistics
  426. ;++ test for duplicate identifiers - see above
  427.  
  428. (define (compile-lambda name vars body-exps outer-shape fn?)
  429.   (let ((cenv (let ((others (shape-cenv outer-shape)))
  430.                 (cond ((null? vars) others) ; ****
  431.                       (else (add-contour vars others)))))
  432.         (spect (arglist->argspectrum vars)) ; unnecessary cons
  433.         (body nil))
  434.     (labels ((shape (object (lambda (lenv genv)
  435.                (object (lambda args           ; return a lexical closure
  436.                    (let ((nargs (compatible-with-argspectrum? args spect)))
  437.                      (cond ((not nargs)
  438.                             (handle-wrong-number-args (or name (disclose shape))
  439.                                                       spect
  440.                                                       args))
  441.                            ((and (fx= (car spect) 0) (not (cdr spect)))
  442.                             (run body lenv genv))
  443.                            (else
  444.                             (run body (add-contour args lenv) genv)))))
  445.                  ((get-environment self) (make-local-env outer-shape lenv))
  446.                  ((get-loaded-file self) (get-loaded-file outer-shape))
  447.                  ((identification self) name)
  448.                  ((argspectrum self) spect)
  449.                  ((disclose self) (disclose shape))))
  450.            ((scode? self) t)
  451.            ((shape-cenv self) cenv)
  452.            ((get-shape self) outer-shape)       ; ???!?
  453.            ((identification self) name)
  454.            ((disclose self)
  455.             `(lambda ,(cond ((and (fx= (car spect) 0) (not (cdr spect)))   '())
  456.                             (else (cenv-first cenv)))
  457.                . ,body-exps))
  458.            ((get-proc-name self)     ;For backtrace!
  459.             (or name (get-proc-name outer-shape)))
  460.            ((get-loaded-file self) (get-loaded-file outer-shape))
  461.            ((disclose-scode self shape) (ignore shape) (disclose self))
  462.            ((print-type-string self) "Open-procedure"))))
  463.     (set *scode-count* (fx+ *scode-count* 1))
  464.     (set body (compile-block body-exps shape nil))
  465.     shape)))
  466.  
  467. (define-operation (shape-cenv shape)
  468.   shape)
  469.  
  470. (define (handle-wrong-number-args name spectrum args)
  471.   (let ((n     (car spectrum))
  472.         (nary? (cdr spectrum)))
  473.     (error (list "wrong number of arguments to procedure -~%"
  474.                  "**~10t~s~%**~10t~s takes~a ~a argument~p.~%")
  475.            (cons name args)
  476.            name
  477.            (if nary? " at least" "")
  478.            n
  479.            n)))
  480.  
  481. (define-compilator (object . stuff) (shape fn?)
  482.   (compile (expand-object-form stuff) shape fn?))
  483.  
  484. ;;; -------------------- Other randomness.
  485.  
  486. (define-compilator (the-environment) (shape fn?)
  487.   (ignore fn?)
  488.   (scode (lambda (lenv genv)
  489.            (ignore genv)
  490.            (make-local-env shape lenv))
  491.          ((disclose-scode self shape)
  492.           (ignore shape)
  493.           '(the-environment))))
  494.  
  495. (define-compilator (bound? var) (shape fn?)
  496.   (ignore fn?)
  497.   (cond ((lambda-bound? shape var)
  498.          (compile-literal t))
  499.         (else
  500.          (scode (lambda (lenv genv)
  501.                   (ignore lenv)
  502.                   (*bound? (genv-env genv) var))))))
  503.  
  504. (define-compilator (lset-variable-value var val) (shape fn?)
  505.   (ignore fn?)
  506.   (compile-lbind var val shape nil))
  507.  
  508. (lset *current-definition* nil)
  509.  
  510. (define (current-definition) *current-definition*)
  511.  
  512. (define-compilator (define-variable-value var val) (shape fn?)
  513.   (ignore fn?)
  514.   (bind ((*current-definition* var))
  515.     (compile-lbind var val shape t)))
  516.  
  517. (define (compile-lbind var val shape define?)
  518.   (cond ((lambda-bound? shape var)
  519.          (warning "~S or ~S on a ~S-bound variable~%  ~G~%"
  520.                   'define 'lset 'lambda
  521.                   `(,(if define? 'define 'lset) ,var ,val))
  522.          (compile `(,(t-syntax 'set-variable-value) ,var ,val)
  523.                   shape nil))
  524.         (else
  525.          (let ((valx (compile val shape nil)))
  526.            (scode (lambda (lenv genv)
  527.                     ((if define? *define *lset)
  528.                      (genv-env genv) var (run valx lenv genv)))
  529.                   ((get-shape self) shape)
  530.                   ((disclose-scode self shape)
  531.                    `(,(if define? 'define 'lset)
  532.                      ,var ,(disclose-scode valx shape))))))))
  533.  
  534. ;;; Local syntax: DEFINE-LOCAL-SYNTAX, LET-SYNTAX
  535.  
  536. (define-compilator (define-local-syntax . spec) (shape fn?)
  537.   (ignore fn?)
  538.   (compile-literal (set-local-syntax *syntax-table* spec)))
  539.  
  540. (define-compilator (let-syntax specs . body) (shape fn?)
  541.   (let ((syntax (make-syntax-table *syntax-table* nil)))
  542.     (walk (lambda (spec)
  543.             (set-local-syntax syntax spec))
  544.           specs)
  545.     (bind ((*syntax-table* syntax))
  546.       (compile-block body shape fn?))))
  547.  
  548. (define (set-local-syntax syntax spec)        ;auxiliary for above
  549.   (let ((pat (car spec))
  550.         (body (cdr spec)))
  551.     (receive (sym exp)
  552.              (cond ((pair? pat)
  553.                     (return (car pat)
  554.                             `(,(t-syntax 'macro-expander) ,pat . ,body)))
  555.                    (else
  556.                     (return pat (car body))))
  557.       (set (syntax-table-entry syntax sym)
  558.            (eval exp (env-for-syntax-definition syntax)))
  559.       sym)))
  560.  
  561. ;++ flush (define-compilator (locale var . body) (shape fn?)
  562. ;  (ignore fn?)
  563. ;  (let ((code (compile-top (blockify body)
  564. ;                           *syntax-table*
  565. ;                           (get-loaded-file shape))))
  566. ;    (scode (lambda (lenv genv)
  567. ;             (let ((new-env (make-locale (make-local-env shape lenv)
  568. ;                                         var)))
  569. ;               (if var
  570. ;                   (bind (((print-env-warnings?) nil))
  571. ;                     (*define new-env var new-env)))
  572. ;               (run-compiled-code code new-env)))
  573. ;           ((disclose-scode self shape)
  574. ;            `(locale ,var ,@body)))))
  575.  
  576. ;;; Implement LABELS as a source rewrite.
  577.  
  578. (define-compilator (labels specs . body) (shape fn?)
  579.   (compile
  580.    (iterate loop ((s specs)
  581.                   (vars '())
  582.                   (inits '()))
  583.     (cond ((null-list? s)
  584.            `((,(t-syntax 'lambda) ,vars
  585.                ,@(reverse! inits)
  586.                . ,body)
  587.              ,@(map (lambda (var) (ignore var) 'unbound-label)
  588.                     vars)))
  589.           (else
  590.            (let ((spec (car s)))
  591.              (cond ((atom? spec)
  592.                     (syntax-error "bad ~S spec~%  (~S (... ~S ...) ...)"
  593.                                   'labels 'labels spec))
  594.                    ((atom? (car spec))
  595.                     (loop (cdr s)
  596.                           (cons (car spec) vars)
  597.                           (cons `(,(t-syntax 'set-variable-value) ,@spec)
  598.                                 inits)))
  599.                    (else
  600.                     (loop (cdr s)
  601.                           (cons (caar spec) vars)
  602.                           (cons `(,(t-syntax 'set-variable-value)
  603.                                   ,(caar spec)
  604.                                   (,(t-syntax 'lambda) ,(cdar spec)
  605.                                                        ,@(cdr spec)))
  606.                                 inits))))))))
  607.   shape fn?))
  608.  
  609. (define-compilator (declare . stuff) (shape fn?)
  610.   (ignore fn?)
  611.   (compile-literal 'declare))
  612.  
  613. (define-compilator (primop . stuff) (shape fn?)
  614.   (ignore fn?)
  615.   (error "primops don't interpret yet -~%~10t~s" '(primop . ,stuff)))
  616.  
  617. (define-compilator (define-foreign . stuff) (shape fn?)
  618.   (ignore fn?)
  619.   (error "foreign definitions don't interpret yet -~%~10t~S" 
  620.          '(define-foreign . ,stuff)))
  621.  
  622. ;;; Generally useful utility:
  623.  
  624. (define (compile-error shape . rest)
  625.   (compile (apply syntax-error rest) shape nil))
  626.  
  627. ;;; -------------------- Variable and environment stuff.
  628.  
  629. ;;; Three primitive operations on variable bindings: fetch, store, locative.
  630.  
  631. (define-compilator (variable-value var) (shape fn?)
  632.   (compile-var var shape fn?))
  633.  
  634. (define (compile-var var shape fn?)
  635.   (and fn?
  636.        (syntax-table-entry *syntax-table* var)
  637.        (warning "call to variable ~S is not being treated as a special form~%"
  638.                 var))
  639.   (cond ((shape-lookup shape var)
  640.          => (lambda (spec) (compile-lexvar spec)))
  641.         (else
  642.          (compile-static shape var))))
  643.  
  644. (define-compilator (set-variable-value var val) (shape fn?)
  645.   (ignore fn?)
  646.   (let ((valx (compile val shape nil)))
  647.     (cond ((shape-lookup shape var)
  648.            => (lambda (spec) (compile-set-lexvar spec valx)))
  649.           (else
  650.            (compile-assign-static valx shape var)))))
  651.  
  652. (define-compilator (var-locative var) (shape fn?)
  653.   (ignore fn?)
  654.   (cond ((shape-lookup shape var)
  655.          => (lambda (spec)
  656.               (scode (lambda (lenv genv)
  657.                        (ignore genv)
  658.                        (lexvar-locative var spec lenv))
  659.                      ((get-shape self) shape))))
  660.         (else
  661.          (compile-static-locative var shape))))
  662.  
  663. ;;; Fetch, store and locative operations for static variables:
  664.  
  665. ;;; Returns a ZZ pair (var . index)
  666.  
  667. (define (get-static-zz var)
  668.   (or (table-entry *free-vars* var)
  669.       (set (table-entry *free-vars* var)
  670.            (cons var (swap *free-var-count* (fx+ *free-var-count* 1))))))
  671.  
  672. (define-integrable (get-locative genv zz)
  673.   (or (vref genv (cdr zz))
  674.       (really-get-locative genv zz)))
  675.  
  676. (define (really-get-locative genv zz)
  677.   (cond ((env-lookup (genv-env genv) (car zz) nil nil)
  678.          => (lambda (loc)
  679.               (vset genv (cdr zz) loc)
  680.               loc))
  681.         (else
  682.          (object nil
  683.            ((contents self)
  684.             (cond ((vref genv (cdr zz)) => contents)
  685.                   (else
  686.                    (error "variable ~S is unbound" (car zz)))))
  687.            ((set-contents self val)
  688.             (cond ((vref genv (cdr zz))
  689.                    => (lambda (loc) (set-contents loc val)))
  690.                   (else
  691.                    (vset genv
  692.                          (cdr zz)
  693.                          (reluctantly-bind (genv-env genv) (car zz)))
  694.                    (set-contents self val))))
  695.            ((locative? self) t)
  696.            ((print-type-string self) "Locative")))))
  697.  
  698. (define (compile-static shape var)
  699.   (let ((zz (get-static-zz var)))
  700.     (scode (lambda (lenv genv)
  701.              (ignore lenv)
  702.              (let ((loc (get-locative genv zz)))
  703.                (cond ((vcell? loc)
  704.                       (let ((z (vcell-contents loc)))
  705.                         (cond ((nonvalue? z)
  706.                                (no-op (error "bound variable ~S has no value"
  707.                                              (car zz))))
  708.                               (else z))))
  709.                      (else
  710.                       (contents loc)))))
  711.            ((get-shape self) shape)
  712.            ((disclose-scode self shape)
  713.             (ignore shape)
  714.             (let ((var (car zz)))
  715.               (cond ((and (symbol? var)
  716.                           (not (syntax-table-entry standard-syntax-table
  717.                                                    var)))
  718.                      var)
  719.                     (else `(variable-value ,var))))))))
  720.  
  721. (define (compile-assign-static valx shape var)
  722.   (let ((zz (get-static-zz var)))
  723.     (scode (lambda (lenv genv)
  724.              (let ((val (run valx lenv genv))
  725.                    (loc (get-locative genv zz)))
  726.                (set-contents loc val)))                  
  727.            ((get-shape self) shape)
  728.            ((disclose-scode self shape)
  729.             `(set ,(car zz) ,(disclose-scode valx shape))))))
  730.  
  731. (define (compile-static-locative var shape)
  732.   (let ((zz (get-static-zz var)))
  733.     (scode (lambda (lenv genv)
  734.              (ignore lenv)
  735.              (get-locative genv zz))
  736.            ((get-shape self) shape))))
  737.  
  738. ;;; Local environment stuff
  739.  
  740. (define (heuristically-lenv? obj)
  741.   (iterate loop ((l obj) (i 0))
  742.     (cond ((lenv-end? l)
  743.            (if (environment? l) obj nil))
  744.           ((not (proper-list? (lenv-first l))) nil)
  745.           ((fx> i 1000) nil)    ; Circularity hack
  746.           (else
  747.            (loop (lenv-rest l) (fx+ i 1))))))
  748.  
  749. (define (lenv-end lenv)
  750.   (cond ((atom? lenv) lenv)
  751.         (else (lenv-end (lenv-rest lenv)))))
  752.  
  753. ;;; Shape lookup stuff.
  754.  
  755. ;;; (SHAPE-LOOKUP shape exp) -> lvspec or false
  756. ;;;     Returns either a local variable spec (lvspec), which is actually
  757. ;;;     a fixnum in two bit fields, or false if the variable isn't
  758. ;;;     locally bound.
  759.  
  760. (define (lambda-bound? shape var)
  761.   (shape-lookup shape var))
  762.  
  763. ;;; Look for local variable in SHAPE; return an LVSPEC if there is
  764. ;;; one.  Returns false if no local variable exists.
  765.  
  766. (define (shape-lookup shape var)
  767.   (iterate loop1 ((v (shape-cenv shape))
  768.                   (m 0))
  769.     (cond ((cenv-end? v) nil)
  770.           (else
  771.            (iterate loop2 ((w (cenv-first v))
  772.                            (n 1))               ; ?
  773.              (cond ((atom? w)
  774.                     (cond ((eq? var w) (lvspec m (fx- 0 n)))
  775.                           (else (loop1 (cenv-rest v) (fx+ m 1)))))
  776.                    ((eq? var (car w))
  777.                     (lvspec m n))       ; success
  778.                    (else
  779.                     (loop2 (cdr w) (fx+ n 1)))))))))
  780.  
  781. (define (make-local-env shape lenv)          
  782.   (cond ((lenv-end? lenv) lenv)
  783.         (else
  784.          (object (lambda (var local? create?)
  785.                    (cond ((or local? create?)
  786.                           (error '("illegal to create new bindings"
  787.                                    " in this environment~%  ~S")
  788.                                  `(env-lookup ... ,var ,local? ,create?)))
  789.                          ((shape-lookup shape var)
  790.                           => (lambda (spec)
  791.                                (lexvar-locative var spec lenv)))
  792.                          (else
  793.                           (env-lookup (lenv-end lenv) var local? create?))))
  794.            ((env-superior self) (lenv-end lenv))
  795.            ((walk-local-env self proc)
  796.             (really-walk-local-env (shape-cenv shape) lenv proc))
  797.            ((crawl-exhibit-env self)
  798.             (format (terminal-output) "Local variable environment:~%")
  799.             (walk-local-env self
  800.                      (lambda (var val)
  801.                        (let ((to (terminal-output)))
  802.                          (format to "  ~8S = " var)
  803.                          (print-one-line val to)
  804.                          (fresh-line to))))
  805.             (format (terminal-output) "Outer environment: ~S~%"
  806.                     (lenv-end lenv)))
  807.            ((get-environment self) self)
  808.            ((get-loaded-file self)
  809.             (get-loaded-file (env-superior self)))
  810.            ((environment? self) t)
  811.            ((print-type-string self) "Environment")))))
  812.  
  813.  
  814. (define-operation (walk-local-env env proc))
  815.  
  816. (define (really-walk-local-env cenv lenv proc)
  817.   (iterate loop1 ((v cenv)
  818.                   (e lenv))
  819.     (cond ((cenv-end? v) nil)
  820.           (else
  821.            (iterate loop2 ((w (cenv-first v))
  822.                            (f (lenv-first e)))
  823.              (cond ((atom? w)
  824.                     (cond ((not (null? w))
  825.                            (proc w f)))
  826.                     (loop1 (cenv-rest v) (lenv-rest e)))
  827.                    (else
  828.                     (proc (car w) (car f))
  829.                     (loop2 (cdr w) (cdr f)))))))))
  830.  
  831. ;;; Given a local variable spec, and the shape to which it's relative,
  832. ;;; return the name of the variable.  This depends on the fact that
  833. ;;; shapes and local environments have the same representation!
  834.  
  835. (define (invert-lvspec shape lvspec)
  836.   (run (compile-lexvar lvspec) (shape-cenv shape) 'lose))
  837.  
  838. ;;; Fetch, store, locative for local variable.
  839.  
  840. (lset *scode-lexvar-count* 0)
  841.  
  842. (define (compile-lexvar spec)
  843.   (set *scode-lexvar-count* (fx+ *scode-lexvar-count* 1))
  844.   spec)
  845.  
  846. (define (compile-set-lexvar spec valx)
  847.   (scode (lambda (lenv genv)
  848.            (store-into-lenv spec lenv (run valx lenv genv)))
  849.          ((disclose-scode self shape)
  850.           `(set ,(invert-lvspec shape spec)
  851.                 ,(disclose-scode valx shape)))))
  852.  
  853. (define (lexvar-locative var spec lenv)
  854.   (object nil
  855.           ((contents self)
  856.            (fetch-from-lenv spec lenv))
  857.           ((set-contents self value)
  858.            (store-into-lenv spec lenv value))
  859.           ((locative? self) t)
  860.           ((identification self) var)
  861.           ((print-type-string self) "Locative")))
  862.  
  863. ;;; Get the value of a local variable.
  864.  
  865. (define (fetch-from-lenv spec lenv)
  866.   (cond ((fx> (lvspec-over spec) 0)     ; conditional moved out of middle
  867.          (let ((back (lvspec-back spec))
  868.                (over (lvspec-over spec)))
  869.             (do ((e1 lenv (lenv-rest e1))
  870.                  (i1 0 (fx+ i1 1)))
  871.                 ((fx= i1 back)
  872.                  (do ((e2 (lenv-first e1) (cdr e2))
  873.                       (i2 1 (fx+ i2 1)))
  874.                      ((fx= i2 over) (car e2)))))))
  875.         (else
  876.          (let ((back (lvspec-back spec))
  877.                (over (lvspec-over spec)))
  878.            (do ((e1 lenv (lenv-rest e1))
  879.                 (i1 0 (fx+ i1 1)))
  880.                ((fx= i1 back)
  881.                 (do ((e2 (lenv-first e1) (cdr e2))
  882.                      (i2 -1 (fx- i2 1)))
  883.                     ((fx= i2 over) e2))))))))
  884.  
  885. ;;; Set the value of a local variable.
  886.  
  887. (define (store-into-lenv spec lenv val)
  888.   (let ((back (lvspec-back spec))
  889.         (over (lvspec-over spec)))
  890.     (do ((e1 lenv (lenv-rest e1))
  891.          (i1 0 (fx+ i1 1)))
  892.         ((fx= i1 back)
  893.          (cond ((fx> over 0)
  894.                 (do ((e2 (lenv-first e1) (cdr e2))
  895.                      (i2 1 (fx+ i2 1)))
  896.                     ((fx= i2 over) (set (car e2) val))))
  897.                (else
  898.                 ;; LENV-FIRST here assumed to be same as CDR!
  899.                 (do ((e2 e1 (cdr e2))
  900.                      (i2 -1 (fx- i2 1)))
  901.                     ((fx= i2 over) (set (cdr e2) val)))))))))
  902.